<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>LinkedList</title>
  </head>
  <body>
    <script>
      // 节点类
      class Node {
        constructor(data) {
          this.data = data;
          this.next = null;
        }
      }
      class LinkedList {
        constructor() {
          this.head = null;
          this.length = 0;
        }
        // 向链表尾部添加一个新的项
        append(element) {
          let newNode = new Node(element);
          if (this.length === 0) {
            this.head = newNode;
          } else {
            let current = this.head;
            while (current.next) {
              current = current.next;
            }
            current.next = newNode;
          }
          this.length += 1;
        }
        // 向链表指定位置添加项
        insert(position, element) {
          // 越界判断
          if (position < 0 || position > this.length) {
            return false;
          }
          let newNode = new Node(element);
          if (position === 0) {
            newNode.next = this.head;
            this.head = newNode;
          } else {
            let current = this.head,
              previous = null,
              index = 0;
            while (index++ < position) {
              previous = current;
              current = current.next;
            }
            newNode.next = current;
            previous.next = newNode;
          }
          this.length += 1;
          return true;
        }
        // 获取对应位置的元素
        get(position) {
          if (position < 0 || position >= this.length) {
            return null;
          }
          let current = this.head,
            index = 0;
          while (index++ < position) {
            current = current.next;
          }
          return current.data;
        }
        // 返回元素在链表中的索引
        indexOf(element) {
          let current = this.head,
            index = 0;
          while (current) {
            if (current.data === element) {
              return index;
            }
            current = current.next;
            index += 1;
          }
          return -1;
        }
        // 修改某个位置元素
        update(position, element) {
          if (position < 0 || position >= this.length) {
            return false;
          }
          let current = this.head,
            index = 0;
          while (index++ < position) {
            current = current.next;
          }
          current.data = element;
          return true;
        }
        // 特定位置移除一项
        removeAt(position) {
          if (position < 0 || position >= this.length) {
            return false;
          }
          let current = this.head;
          if (position === 0) {
            this.head = current.next;
          } else {
            let index = 0,
              previous = null;
            while (index++ < position) {
              previous = current;
              current = current.next;
            }
            previous.next = current.next;
          }
          this.length -= 1;
          return current.data;
        }
        // 从链表移除一项
        remove(element) {
          let position = this.indexOf(element);
          return this.removeAt(position);
        }
        // 链表是否为空
        isEmpty() {
          return this.length === 0;
        }
        // 返回链表包含元素个数
        size() {
          return this.length;
        }
        // 输出元素的值
        toString() {
          let current = this.head,
            str = "";
          while (current) {
            str += current.data + " ";
            current = current.next;
          }
          return str;
        }
      }
      let list = new LinkedList();
      list.append("a");
      list.append("b");
      list.append("c");
      list.append("d");
      list.append("e");
      // console.log(list.update(2, "x"));
      // console.log(list.toString());
      // console.log(list.indexOf("x"));
      console.log(list.removeAt(2));
      console.log(list.remove("b"));
      console.log(list.toString());
    </script>
  </body>
</html>
